Step 1: Compile & Assemble your C program with ELVM
C code
// You can run a larger C program (FizzBuzz) by changing this condition. // Note you may not want to do this for slower backends (e.g., Brainfuck). #if 1 int putchar(int c); int main() { const char* p = "Hello, world!\n"; for (int i = 0; i < 20; i++) putchar(p[i]); return 0; } #else int putchar(int c); int div(int a, int b){ int result = 0; while(a >= b){ a -= b; result++; } return result; } int mod(int a, int b){ int result = 0; while(a >= b){ a -= b; } return a; } const char* str = "FizzBuzz"; void fizz() { for (int i = 0; i < 4; i++) putchar(str[i]); } void buzz() { for (int i = 4; i < 8; i++) putchar(str[i]); } int isDivisible(int a, int b){ return mod(a, b) == 0; } int printNum(int num){ if(num >= 10){ putchar(48 + div(num, 10)); } putchar(48 + mod(num, 10)); } int main() { for (int i = 1; i <= 10; i++) { int div5 = isDivisible(i, 5); int div3 = isDivisible(i, 3); if(div3 && div5){ fizz(); buzz(); }else if(div3){ fizz(); }else if(div5){ buzz(); }else{ printNum(i); } putchar('\n'); } return 0; } #endif
ELVM IR
"Compile" generates ELVM IR.
"Assemble" assembles IR into prototyping vm instructions. First run can be a bit slow.
Step 1 (alternate): Assemble lower level program
Assembly + Labels
// Asks for your name, then prints "Hello,
!" // Print "Your name: " IMM 89 0 PUTC IMM 111 0 PUTC IMM 117 0 PUTC IMM 114 0 PUTC IMM 32 0 PUTC IMM 110 0 PUTC IMM 97 0 PUTC IMM 109 0 PUTC IMM 101 0 PUTC IMM 58 0 PUTC IMM 32 0 PUTC .L1 // Read in the input GETC // Echo input PUTC // Store in memory at register A REG a 1 STORE // Jump to L2 if input is a newline IMM 10 1 EQ IMM 2 2 CJMP // A++ REG a 0 IMM 1 1 ADD RES a // Jump to .L1 IMM 0 1 IMM 1 2 CJMP .L2 // Print "Hello, " IMM 72 0 PUTC IMM 101 0 PUTC IMM 108 0 PUTC IMM 108 0 PUTC IMM 111 0 PUTC IMM 44 0 PUTC IMM 32 0 PUTC // Print the stored name // Use register B as a counter .L3 REG b 1 LOAD PUTC // b++ REG b 0 IMM 1 1 ADD RES b // Note that a represents the index of the last character, which is the newline // character at the end. To avoid the newline, we break if b>=a REG a 1 IMM 4 2 GE CJMP // Otherwise, loop back to .L3 IMM 1 0 IMM 3 2 CJMP .L4 // End with ! IMM 33 0 PUTC EXIT // // Store 0 into A // IMM 0 0 // RES a // .L1 // // Print some stuff // REG a 0 // IMM 49 1 // ADD // PUTC // IMM 10 0 // PUTC // // a++ // REG a 0 // IMM 1 1 // ADD // RES a // // if a < 12 loop // IMM 12 1 // LT // IMM 1 2 // CJMP // EXIT
Data (each line is data entry)
Step 2: Validate using JS runtime
Assembled code
JS Runtime output
Input:
Program memory size:
-
variables (assemble to update)
Dispatch memory size:
-
variables (assemble to update)
Data memory size:
-
variables (assemble to update) - you may need more for dynamic mem access
Runtime instructions:
-
(run to update)
Runtime memory use:
-
(run to update)
"Run" uses JS-based vm to run the assembled code.
Step 3: Load into figma!!